/* 
 * File:   LambertianShader.cpp
 * Author: brady
 * 
 * Created on August 5, 2011, 11:09 PM
 */

#include <shaders/LambertianShader.h>


LambertianShader::LambertianShader() {
}

LambertianShader::LambertianShader(const LambertianShader& orig) {
}

LambertianShader::~LambertianShader() {
}

Vector3D LambertianShader::shade(IntersectionResult& result) const {
    //the sum of the light hitting the object
    Vector3D totalLight = computeLighting(result);
    //the color of the object at the point of intersection
    Vector3D pointColor = result.shape->texture->getColor(result);
    Vector3D finalColor = pointColor.mix(totalLight) + gParams.scene->ambientColor;
    return finalColor;
}


double LambertianShader::getLambertianCoeffecient(const Vector3D &normal, const Vector3D &toLight) const {
    double shadeCoeff = normal.dot(toLight);
    if (shadeCoeff < 0.0) return 0.0;
    else return shadeCoeff;
}

Vector3D LambertianShader::computeLighting(IntersectionResult& result) const {
    Vector3D totalLight(0,0,0);
    const Vector3D& point(result.hitPoint);
    const vector<Light*>& lights = gParams.scene->lights;

    int lightCount = lights.size();
    for(int i = 0; i < lightCount; i++){
        Light* curLight = lights[i];
        Vector3D samplePoint = curLight->getSamplePoint(result);
        double shadowCoeff = 0;
            Vector3D toLight = samplePoint - point;
            double lightDistance = toLight.magnitude();
            toLight.normalize();

            Ray lightSampleRay = Ray(result.hitPoint, toLight);

            //Test for shadows
            //if lightray hits an object, shadow coeff = 0.0
            //otherwise compute the shadow coefficient to unobstructed light

            //Try limiting or disabling this section to rule out or in Shadow detection
            IntersectionParams shadowParams(lightSampleRay, FLT_EPSILON, lightDistance);
            IntersectionResult occluder = gParams.scene->intersectionStructure->getAnyIntersection(shadowParams);
            if (occluder.shape != NULL) {
                shadowCoeff = 0.0;
            }
            else {
                    shadowCoeff = getLambertianCoeffecient(result.shape->texture->getNormal(result), toLight);
            }
        totalLight += (curLight->getColor() * shadowCoeff);
    }
    return totalLight;
}